/*
 * Copyright 2023, Haiku, Inc.
 * Distributed under the terms of the MIT License.
 *
 * Authors:
 *		Haiku Team
 */


#include "loongarch64.h"

#include <KernelExport.h>
#include <OS.h>
#include <cpu.h>
#include <debug.h>


//#define TRACE_LOONGARCH64
#ifdef TRACE_LOONGARCH64
#	define TRACE(x...) dprintf("loongarch64_cpu: " x)
#else
#	define TRACE(x...) ;
#endif


// CPU 模块接口
static int32 cpu_module_init(kernel_args* args);
static status_t cpu_module_uninit(void);


// 全局变量
static uint32 sCPUFeatures = 0;
static char sCPUVendorID[17] = { 0 };
static char sCPUBrandString[65] = { 0 };


// 读取CSR寄存器
static inline uint64
read_csr(uint32 reg)
{
	uint64 value;
	asm volatile("csrrd %0, %1" : "=r"(value) : "i"(reg));
	return value;
}


// 写入CSR寄存器
static inline void
write_csr(uint32 reg, uint64 value)
{
	asm volatile("csrwr %0, %1" :: "r"(value), "i"(reg));
}


// 识别CPU型号和特性
status_t
loongarch64_identify_cpu(void)
{
	TRACE("识别LoongArch64 CPU...\n");
	
	// 读取CPU ID
	uint64 cpuid = read_csr(LOONGARCH_CSR_CPUID);
	TRACE("CPUID: 0x%llx\n", cpuid);
	
	// 解析CPUID
	uint32 companyID = (cpuid >> 32) & 0xFFFF;
	uint32 processorID = (cpuid >> 16) & 0xFFFF;
	uint32 revision = cpuid & 0xFFFF;
	
	TRACE("Company ID: 0x%x, Processor ID: 0x%x, Revision: 0x%x\n", 
		companyID, processorID, revision);
	
	// 设置CPU厂商信息
	if (companyID == 0x14C) {
		strlcpy(sCPUVendorID, "Loongson", sizeof(sCPUVendorID));
	} else {
		strlcpy(sCPUVendorID, "Unknown", sizeof(sCPUVendorID));
	}
	
	// 设置CPU型号信息
	snprintf(sCPUBrandString, sizeof(sCPUBrandString), 
		"Loongson Processor (ID: 0x%x, Rev: 0x%x)", processorID, revision);
	
	// 检测CPU特性
	uint64 prcfg1 = read_csr(LOONGARCH_CSR_PRCFG1);
	uint64 prcfg2 = read_csr(LOONGARCH_CSR_PRCFG2);
	uint64 prcfg3 = read_csr(LOONGARCH_CSR_PRCFG3);
	
	TRACE("PRCFG1: 0x%llx, PRCFG2: 0x%llx, PRCFG3: 0x%llx\n", 
		prcfg1, prcfg2, prcfg3);
	
	// 检查LSX支持
	if (prcfg1 & (1ULL << 6))
		sCPUFeatures |= LOONGARCH64_FEATURE_LSX;
	
	// 检查LASX支持
	if (prcfg1 & (1ULL << 7))
		sCPUFeatures |= LOONGARCH64_FEATURE_LASX;
	
	// 检查LBT支持
	if (prcfg1 & (1ULL << 12))
		sCPUFeatures |= LOONGARCH64_FEATURE_LBT;
	
	// 检查复数计算扩展支持
	if (prcfg1 & (1ULL << 13))
		sCPUFeatures |= LOONGARCH64_FEATURE_COMPLEX;
	
	// 检查加密扩展支持
	if (prcfg1 & (1ULL << 14))
		sCPUFeatures |= LOONGARCH64_FEATURE_CRYPTO;
	
	// 检查虚拟化扩展支持
	if (prcfg1 & (1ULL << 15))
		sCPUFeatures |= LOONGARCH64_FEATURE_VIRTUALIZATION;
	
	TRACE("CPU特性: 0x%x\n", sCPUFeatures);
	
	return B_OK;
}


// 初始化CPU
void
loongarch64_init_cpu(void)
{
	TRACE("初始化LoongArch64 CPU...\n");
	
	// 这里可以添加特定于LoongArch64的CPU初始化代码
	// 例如设置特定的CSR寄存器或启用特定的CPU功能
}


// 获取CPU特性
uint32
loongarch64_get_cpu_features(void)
{
	return sCPUFeatures;
}


// 设置CPU特性
void
loongarch64_set_cpu_features(uint32 features)
{
	sCPUFeatures = features;
}


// 获取CPU厂商字符串
const char*
loongarch64_get_cpu_vendor_string(void)
{
	return sCPUVendorID;
}


// 获取CPU型号字符串
const char*
loongarch64_get_cpu_model_string(void)
{
	return sCPUBrandString;
}


// CPU模块初始化
static int32
cpu_module_init(kernel_args* args)
{
	TRACE("cpu_module_init\n");
	
	status_t status = loongarch64_identify_cpu();
	if (status != B_OK)
		return status;
	
	loongarch64_init_cpu();
	
	return B_OK;
}


// CPU模块卸载
static status_t
cpu_module_uninit(void)
{
	TRACE("cpu_module_uninit\n");
	return B_OK;
}


// 模块定义
static cpu_module_info sLoongArch64Module = {
	{
		B_CPU_MODULE_NAME,
		B_KEEP_LOADED,
		cpu_module_init,
		cpu_module_uninit
	},
	
	loongarch64_identify_cpu,
	loongarch64_get_cpu_vendor_string,
	loongarch64_get_cpu_model_string
};


module_info* modules[] = {
	(module_info*)&sLoongArch64Module,
	NULL
};